
import java.io.*;
import java.net.Socket;
import javax.sound.sampled.*;
import java.io.IOException;
import java.io.OutputStream;
import java.util.concurrent.TimeUnit;


public class VoiceChatClient {
    private Socket socket;
    private boolean isConnected = false;
    private AudioFormat audioFormat;
    private TargetDataLine targetDataLine;
    private SourceDataLine sourceDataLine;
    private boolean reconnecting = false;
    private static final int RECONNECT_DELAY = 3; // 重新连接延迟时间（秒）

    public static void main(String[] args) {
        VoiceChatClient client = new VoiceChatClient();
        client.connect();
        client.startVoiceChat();
    }

    public void connect() {
        while (!isConnected) {
            try {
                socket = new Socket("192.168.41.21", 8888);
                isConnected = true;
                reconnecting = false;
                System.out.println("已连接到服务器");
            } catch (IOException e) {
                if (!reconnecting) {
                    System.out.println("连接服务器失败，" + RECONNECT_DELAY + "秒后重试...");
                    try {
                        TimeUnit.SECONDS.sleep(RECONNECT_DELAY);
                    } catch (InterruptedException ex) {
                        ex.printStackTrace();
                    }
                }
            }
        }
    }

    public void startVoiceChat() {
        try {
            audioFormat = new AudioFormat(44100, 16, 1, true, false);
            // 启动采集和发送语音数据的线程
            Thread sendThread = new Thread(() -> {
                try {
                    OutputStream outputStream = socket.getOutputStream();
                    DataLine.Info dataLineInfo = new DataLine.Info(TargetDataLine.class, audioFormat);
                    targetDataLine = (TargetDataLine) AudioSystem.getLine(dataLineInfo);
                    targetDataLine.open(audioFormat);
                    targetDataLine.start();
                    byte[] buffer = new byte[2048];
                    int bytesRead;
                    while (isConnected && (bytesRead = targetDataLine.read(buffer, 0, buffer.length))!= -1) {
                        outputStream.write(buffer, 0, bytesRead);
                    }
                    targetDataLine.close();
                } catch (Exception e) {
                    handleDisconnect(e);
                }
            });
            sendThread.start();

            // 启动接收和播放语音数据的线程
            Thread receiveThread = new Thread(() -> {
                try {
                    InputStream inputStream = socket.getInputStream();
                    DataLine.Info dataLineInfo = new DataLine.Info(SourceDataLine.class, audioFormat);
                    sourceDataLine = (SourceDataLine) AudioSystem.getLine(dataLineInfo);
                    sourceDataLine.open(audioFormat);
                    sourceDataLine.start();
                    byte[] buffer = new byte[1024];
                    int bytesRead;
                    while (isConnected && (bytesRead = inputStream.read(buffer))!= -1) {
                        sourceDataLine.write(buffer, 0, bytesRead);
                    }
                    if (sourceDataLine.isOpen()) {
                        sourceDataLine.drain();
                        sourceDataLine.close();
                    }
                } catch (Exception e) {
                    handleDisconnect(e);
                }finally {
                    if (sourceDataLine != null && sourceDataLine.isOpen()) {
                        sourceDataLine.close();
                    }
                }
            });
            receiveThread.start();

            // 等待发送和接收线程完成（这里只是简单等待，实际可能需要更复杂的逻辑来处理线程的结束）
            try {
                sendThread.join();
                receiveThread.join();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private void handleDisconnect(Exception e) {
        if (e instanceof IOException && ((IOException) e).getMessage().contains("Connection reset by peer")) {
            isConnected = false;
            try {
                socket.close();
            } catch (IOException ex) {
                ex.printStackTrace();
            }
            System.out.println("连接已断开，等待 " + RECONNECT_DELAY + " 秒后重新连接...");
            reconnecting = true;
            try {
                TimeUnit.SECONDS.sleep(RECONNECT_DELAY);
            } catch (InterruptedException ex) {
                ex.printStackTrace();
            }
            connect();
            if (isConnected) {
                startVoiceChat();
            }
        } else {
            e.printStackTrace();
        }
    }
}
